package controller

import (
	"encoding/json"
	"gdfs-center/controller/ao"
	"gdfs-center/controller/vo"
	"gdfs-center/db"
	"gdfs-center/engine"
	"gdfs-center/err"
	"gdfs-center/logcat"
	"gdfs-center/socket/cmdGenerate"
	"gdfs-center/socket/codec"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"log"
)

func equalNodeName(nodename string) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		return db.Where("node_name = ?", nodename)
	}
}

func GetNodeList(c *gin.Context) {
	c.Writer.Header().Set("content-type", "application/json")
	var nodelistao ao.NodeListAo
	var pageresult vo.PageResult
	jsonerr := json.Unmarshal(GetPostJson(c.Request), &nodelistao)
	if jsonerr != nil {
		logcat.GetLog().Sugar().Info("###jsonerr:", jsonerr)
		WritedString(c.Writer, false, err.JSONERR, err.Errortype[err.JSONERR], pageresult)
		return
	}
	if nodelistao.PageNum == 0 {
		WritedString(c.Writer, false, err.NOTVALID_ERROR, err.Errortype[err.NOTVALID_ERROR], pageresult)
		return
	}
	if nodelistao.PageSize == 0 {
		WritedString(c.Writer, false, err.NOTVALID_ERROR, err.Errortype[err.NOTVALID_ERROR], pageresult)
		return
	}
	var scopes []func(*gorm.DB) *gorm.DB
	if nodelistao.NodeName != "" {
		scopes = append(scopes, equalNodeName(nodelistao.NodeName))
	}
	var total int64
	var nodes []db.Node
	db.GetPageQueryTotal(scopes).Find(&nodes).Count(&total)
	db.PageQuery(scopes, nodelistao.PageSize, nodelistao.PageNum, "").Find(&nodes)
	var nodelistvos []vo.NodeListVo
	for _, n := range nodes {
		var nodevo vo.NodeListVo
		nodevo.NodeId = n.NodeId
		log.Println("#####nodename =", n.NodeName, "###nodeid=", n.NodeId)
		nodevo.NodeName = n.NodeName
		var storetemp []db.Store
		var instancecount int64
		db.GetDB().Where("node_id = ?", n.NodeId).Find(&storetemp).Count(&instancecount)
		nodevo.InstanceCount = int(instancecount)
		var healthyCount int
		for _, s := range storetemp {
			if _, ok := engine.GetEngine().StoreMap[s.StoreId]; ok {
				if engine.GetEngine().StoreMap[s.StoreId].IsAlive() {
					if healthyCount < int(instancecount) {
						healthyCount++
					}
				}
			}
		}
		nodevo.HealthyCount = healthyCount
		nodelistvos = append(nodelistvos, nodevo)
	}
	pageresult.PageNum = nodelistao.PageNum
	pageresult.PageSize = nodelistao.PageSize
	pageresult.Pages = int(total) / nodelistao.PageSize
	pageresult.Total = total
	pageresult.List = nodelistvos
	WritedString(c.Writer, true, "0", "处理成功", pageresult)
}

//绑定节点
func Bindnode(c *gin.Context) {
	c.Writer.Header().Set("content-type", "application/json")
	var ao ao.BindNodeAo
	jsonerr := json.Unmarshal(GetPostJson(c.Request), &ao)
	if jsonerr != nil {
		logcat.GetLog().Sugar().Info("###jsonerr:", jsonerr)
		WritedString(c.Writer, false, err.JSONERR, err.Errortype[err.JSONERR], nil)
		return
	}
	if ao.NodeName == "" {
		WritedString(c.Writer, false, err.NOTVALID_ERROR, err.Errortype[err.NOTVALID_ERROR], nil)
		return
	}
	if ao.StoreId == "" {
		WritedString(c.Writer, false, err.NOTVALID_ERROR, err.Errortype[err.NOTVALID_ERROR], nil)
		return
	}
	var store db.Store
	db.GetDB().Where("store_id = ? AND node_id = ?", ao.StoreId, "").First(&store)
	if store == (db.Store{}) {
		WritedString(c.Writer, false, err.DUPLICATEBIND, err.Errortype[err.DUPLICATEBIND], nil)
		return
	}
	var node db.Node
	db.GetDB().Where("node_name = ?", ao.NodeName).First(&node)
	if node != (db.Node{}) {
		store.NodeId = node.NodeId
		db.GetDB().Save(&store)
		engine.BindNode(node.NodeId, ao.StoreId)
		if _, ok := engine.GetEngine().StoreMap[ao.StoreId]; ok {
			s := engine.GetEngine().StoreMap[ao.StoreId]
			if s.IsAlive() {
				var stores []db.Store
				var nstores codec.NoticeNodeCmd
				db.GetDB().Where("node_id = ?", node.NodeId).Find(&stores)
				if len(stores) > 0 {
					for _, st := range stores {
						var nstore codec.NoticeStore
						nstore.StoreId = st.StoreId
						nstore.StoreIp = st.StoreIp
						nstore.HttpPort = st.HttpPort
						nstores.NoticeStores = append(nstores.NoticeStores, nstore)
					}
				}
				nstores.NodeID = node.NodeId
				s.Conn.Write(cmdGenerate.GenerateNotisNode(nstores))
			}
		}
		WritedString(c.Writer, true, err.SUCESS, err.Errortype[err.SUCESS], nil)
		return
	}
	WritedString(c.Writer, false, err.SYSTEMERR, err.Errortype[err.SYSTEMERR], nil)
}

func GetNodeIdAndNameList(c *gin.Context) {
	c.Writer.Header().Set("content-type", "application/json")
	var vos []vo.NodeIdAndNameListVo
	var nodes []db.Node
	db.GetDB().Find(&nodes)
	for _, n := range nodes {
		var vo vo.NodeIdAndNameListVo
		vo.NodeName = n.NodeName
		vo.NodeId = n.NodeId
		vos = append(vos, vo)
	}
	WritedString(c.Writer, true, "0", "处理成功", vos)
}

//获取节点名称列表
func GetNodeNameList(c *gin.Context) {
	c.Writer.Header().Set("content-type", "application/json")
	var vos []vo.GetNodeNameListVo
	var nodes []db.Node
	db.GetDB().Select("node_name").Find(&nodes)
	for _, n := range nodes {
		var vo vo.GetNodeNameListVo
		vo.NodeName = n.NodeName
		vos = append(vos, vo)
	}
	WritedString(c.Writer, true, "0", "处理成功", vos)
}
